#pragma once 

#include <iostream>
#include <vector>
#include <string>
#include <semaphore.h>
#include <pthread.h>

template<typename T>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }
    void Lock(pthread_t &mutex)
    {
        pthread_lock(&mutex);
    }
    void Unlock(phtread_t &mutex)
    {
        pthread_unlock(&mutex);
    }
public:
    RingQueue(int cap):_cap(cap), _ring_queue(_cap),_productor_setp(0),_consumer_setp(0)
    {
        sem_init(&_room_sem, 0, _cap);
        sem_init(&_data_sem, 0, 0);

        pthread_mutex_init(&_productor_mutex);
        pthread_mutex_init(&_consumer_mutex);

    }
    void Enqueue(const T& in)
    {
        //生产行为
        P(_room_sem);
        //一定有空间
        Lock(_productor_mutex);
        _ring_queue[_productor_setp++] = in;
        _productor_setp %= _cap;
        Unlock(_productor_mutex);
        V(_data_sem);
    }
    void Pop(T* out)//输出型参数
    {
        //消费行为
        P(_data_sem);
        Lock(&_consumer_mutex);
        *out = _ring_queue[_consumer_setp++];
        _consumer_setp %= _cap;
        Unlock(_consumer_mutex);
        V(_room_sem);
    }
    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);
        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }
private:
    // 1. 环形队列
    int _cap; // 环形队列的容量上限
    std::vector<T> _ring_queue;

    // 2. 生产者和消费者的下标
    int _productor_setp;
    int _consumer_setp;

    // 3. 信号量的定义
    sem_t _room_sem;
    sem_t _data_sem;

    // 4. 定义锁，维护多生产和消费的关系
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
};